Avoid allocating the CandidateSet when there's a single match - #9622
Conversation
- Add fast path for 0 route values, and policies
| public RouteValueDictionary RouteValues | ||
| { | ||
| get => _routeValues; | ||
| get => _routeValues ?? (_routeValues = new RouteValueDictionary()); |
There was a problem hiding this comment.
If we're going to do this, we can take advantage of it in more cases, including the ones that involve cnadidate set.
There was a problem hiding this comment.
This is beyond the scope of this PR, but what about reusing RVD instances? It would be similar to how we're reusing HttpContext et al. It's basically a per-request allocation that is tied to the route values feature.
Reusing RVD, and the routing feature, would save allocations on every request, not just those with no route values.
There was a problem hiding this comment.
We can just straight up do this in Kestrel I fear we won't be able to do the more generic caching for 3.0
There was a problem hiding this comment.
If we're going to do this, we can take advantage of it in more cases, including the ones that involve cnadidate set.
Yes, we can, I just wanted to minimize the code change for now. I have to look at see what things are assuming route values are never null when looking at CandidateState.RouteValues (maybe I can do it statiaclly with #enable nullable 😄 )
There was a problem hiding this comment.
CandidateSet has some special semantics around RVD that should just be removed. If treats null RVD as a shorthand for not-a-match in some APIs.
|
####?s |
Will get some. I went awaty but now I'm back |
| _selector = selector; | ||
| _states = states; | ||
| _maxSegmentCount = maxSegmentCount; | ||
| _isDefaultEndpointSelector = selector is DefaultEndpointSelector; |
There was a problem hiding this comment.
I'd feel slightly better if this was an exact type equality check. This isn't public, but that would capture the intent better.
There was a problem hiding this comment.
Isn’t it sealed? Future proofing?
Scenario, hello world plaintext (the /plaintext sample in the RoutingSandbox) hit with 10K requests.
Allocations before:
Allocations after:
Microbenchmarks:
MatcherSingleEntryBenchmark
Before:
After: